﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GrayParrot.Configuration
{
    /// <summary>
    /// Configuration Manager Helper class...
    /// </summary>
    /// <example>
    /// 
    /// The definition of the configuration section follows the classic System.Configuration way:
    /// 
    /// A definition for the section in .config file is:
    ///<code>  
    ///  <sectionGroup name="pageAppearanceGroup">
    ///      <section name="pageAppearance" type="Test.PageAppearanceSection, Test"
    ///                                     allowLocation="true" allowDefinition="Everywhere" />
    ///  </sectionGroup>
    ///</code>
    ///
    /// The section is needed, but you can leave it empty. It is used by the standard System.Configuration to 
    /// load the types for the section:
    ///<code> 
    ///   <pageAppearanceGroup>
    ///       <pageAppearance remoteOnly="true">
    ///           <font name="" size=""/>
    ///           <color background="" foreground=""/>
    ///       </pageAppearance>
    ///   </pageAppearanceGroup>
    ///</code>
    ///
    /// You will need to define the connection string that you specify as parameter of the <seealso cref="DatabaseConfigurationSectionAttribute"/> attribute
    ///<code> 
    ///   <connectionStrings>
    ///      <add name="cfngCN" connectionString="Data Source=MELNAC-PC\SQLEXPRESS;Initial Catalog=BrokerDemo;Integrated Security=True" />
    ///   </connectionStrings>
    /// </code>
    /// 
    /// To create the table that contains the configurations in the database, run the SQL code in DatabaseScript.txt.
    /// Remember to replace the 'DEFINE_HERE_THE_TABLE_NAME' placeholder with the choosen name of the table.
    ///  
    /// Decorate your ConfigurationSection class with the <seealso cref="DatabaseConfigurationSectionAttribute"/> attribute
    /// as follow:
    /// <code>
    ///     [DatabaseConfigurationSectionAttribute(ConnectionStringName = "cfngCN", TableName="Configurations")]
    ///     public class PageAppearanceSection : ConfigurationSectionEx
    ///     {
    ///     :
    ///     }
    /// </code>
    /// 
    /// Example of reading a section...
    /// <code>
    ///     PageAppearanceSection confige3 = ConfigurationManagerHelper.Get<PageAppearanceSection>("pageAppearance2");
    ///</code>
    ///
    /// Example of read/write...
    /// <code>
    ///     bool result = ConfigurationManagerHelper.Save(p =>
    ///     {
    ///         PageAppearanceSection config = (PageAppearanceSection)p.GetSection("pageAppearanceGroup/pageAppearance");
    ///
    ///         string m_name = config.Font.Name;
    ///         int m_size = config.Font.Size;
    ///
    ///          config.Font.Name = "FontName new value";
    ///     });
    ///</code> 
    /// </example>
    public class ConfigurationManagerHelper : IConfigurationManagerHelper
    {
        public static Exception Exception { get; set; }

        public static T Get<T>(string sectionName)
        {
            T retValue = default(T);

            try
            {
                retValue = (T)ConfigurationManager.GetSection(sectionName);
            }
            catch (Exception ex)
            {
                Exception = ex;
            }

            return retValue;
        }

        public static bool Save(Action<System.Configuration.Configuration> action)
        {
            bool retValue = false;

            try
            {
                System.Configuration.Configuration exeConfiguration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

                action(exeConfiguration);

                exeConfiguration.Save();

                retValue = true;
            }
            catch (Exception ex)
            {
                Exception = ex;
            }

            return retValue;
        }
    }
}
